/**
 * 
 */
package com.wilmar.process.core.services.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jbpm.api.Execution;
import org.jbpm.api.ProcessDefinition;
import org.jbpm.api.ProcessEngine;
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.TaskQuery;
import org.jbpm.api.task.Participation;
import org.jbpm.api.task.Task;

import com.wilmar.common.util.PageinationEntity;
import com.wilmar.process.core.ProcessSystemDeclareKeys;
import com.wilmar.process.core.services.api.ISystemProcessInstanceService;
import com.wilmar.process.core.services.api.ISystemProcessLogService;
import com.wilmar.process.core.services.api.ISystemTaskInstanceService;
import com.wilmar.process.core.services.spi.IOrganizationService;
import com.wilmar.process.core.services.spi.IRoleService;
import com.wilmar.process.dao.api.ITaskInstanceQueryDAO;
import com.wilmar.process.entity.CountersignInfo;
import com.wilmar.process.entity.InstanceOperateOpinion;
import com.wilmar.process.entity.Organization;
import com.wilmar.process.entity.ProcessInstanceHelper;
import com.wilmar.process.entity.ProcessLog;
import com.wilmar.process.entity.Role;
import com.wilmar.process.entity.TaskInstanceProperties;
import com.wilmar.process.entity.User;
import com.wilmar.process.entity.query.ProcessTakenTaskQueryObject;
import com.wilmar.process.entity.query.ProcessUnassignTaskQueryObject;
import com.wilmar.process.entity.vo.TaskInstanceVO;
import com.wilmar.process.enumerate.EnumProcessInstanceFixedVariableNameSet;
import com.wilmar.process.enumerate.EnumProcessLogLevel;
import com.wilmar.process.enumerate.EnumProcessOperateOpinionType;
import com.wilmar.process.enumerate.EnumSystemQueryNameSet;
import com.wilmar.process.enumerate.EnumTaskInstanceQueryParamNameSet;
import com.wilmar.process.exception.ObjectNotFoundException;
import com.wilmar.process.exception.PermissionDeniedException;
import com.wilmar.process.exception.TaskAlreadyProcessedException;
import com.wilmar.process.exception.TaskAlreadyTakenByAnotherUserException;
import com.wilmar.process.exception.TaskRepeatAcceptedException;

/**
 * @author MaKuBEX E-mail:makubexnet@gmail.com
 * @version 2.0.1 at Aug 4, 2009 6:11:14 PM
 * 
 */
public class SystemTaskInstanceServiceImpl implements
		ISystemTaskInstanceService {

	private ProcessEngine processEngine;

	private IRoleService roleService;
	private IOrganizationService organizationService;
	private ITaskInstanceQueryDAO taskInstanceQueryDAO;
	private ISystemProcessLogService systemProcessLogService;
	private ISystemProcessInstanceService systemProcessInstanceService;

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#completeTask(java.lang.String,
	 *      java.lang.String, com.wilmar.process.entity.User)
	 */
	public synchronized void completeTask(String taskInstanceId,
			String outCome, User user, InstanceOperateOpinion opinion,
			Map<String, ?> variableMap, boolean forceComplete)
			throws PermissionDeniedException {
		Task taskInstance = this.processEngine.getTaskService().getTask(
				taskInstanceId);
		if (!forceComplete
				&& !user.getId().equalsIgnoreCase(taskInstance.getAssignee())) {
			throw new PermissionDeniedException(
					"This task is not assigned to you! You can't complete it!");
		} else {
			ProcessInstanceHelper helper = (ProcessInstanceHelper) this.processEngine
					.getTaskService()
					.getVariable(
							taskInstanceId,
							EnumProcessInstanceFixedVariableNameSet.PROCESS_INSTANCE_HELPER
									.toString());
			helper.setLastestOperator(user);
			helper.addOperator(user);
			helper.setLastestTaskInstanceId(taskInstanceId);
			CountersignInfo countersignInfo = (CountersignInfo) this.processEngine
					.getTaskService()
					.getVariable(
							taskInstanceId,
							EnumProcessInstanceFixedVariableNameSet.COUNTERSIGN_TASK_INFO_PREFIX
									.toString()
									+ ProcessSystemDeclareKeys.UNDERLINE
									+ taskInstance.getActivityName());
			Map<String, Object> varMap = new HashMap<String, Object>();
			if (countersignInfo != null) {
				countersignInfo.appendDecidition(user, outCome);
				varMap
						.put(
								EnumProcessInstanceFixedVariableNameSet.COUNTERSIGN_TASK_INFO_PREFIX
										.toString()
										+ ProcessSystemDeclareKeys.UNDERLINE
										+ taskInstance.getActivityName(),
								countersignInfo);
			}
			if (variableMap != null)
				varMap.putAll(variableMap);
			varMap
					.put(
							EnumProcessInstanceFixedVariableNameSet.PROCESS_INSTANCE_HELPER
									.toString(), helper);
			TaskInstanceVO taskVO = this.convertToVO(taskInstance);
			this.processEngine.getTaskService().completeTask(taskInstanceId,
					outCome, varMap);
			this.systemProcessLogService.saveOperateLog(taskVO
					.getProcessInstanceId(), helper.getProcessDefinitionName(),
					taskInstance, user, opinion, outCome);
		}
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#completeTask(java.lang.String,
	 *      com.wilmar.process.entity.User)
	 */
	public synchronized void completeTask(String taskInstanceId, User user,
			InstanceOperateOpinion opinion, Map<String, ?> variableMap,
			boolean forceComplete) throws PermissionDeniedException {
		Task taskInstance = this.processEngine.getTaskService().getTask(
				taskInstanceId);
		if (!forceComplete
				&& !user.getId().equalsIgnoreCase(taskInstance.getAssignee())) {
			throw new PermissionDeniedException(
					"This task is not assigned to you! You can't complete it!");
		} else {
			ProcessInstanceHelper helper = (ProcessInstanceHelper) this.processEngine
					.getTaskService()
					.getVariable(
							taskInstanceId,
							EnumProcessInstanceFixedVariableNameSet.PROCESS_INSTANCE_HELPER
									.toString());
			helper.setLastestOperator(user);
			helper.addOperator(user);
			helper.setLastestTaskInstanceId(taskInstanceId);
			CountersignInfo countersignInfo = (CountersignInfo) this.processEngine
					.getTaskService()
					.getVariable(
							taskInstanceId,
							EnumProcessInstanceFixedVariableNameSet.COUNTERSIGN_TASK_INFO_PREFIX
									.toString()
									+ ProcessSystemDeclareKeys.UNDERLINE
									+ taskInstance.getActivityName());
			Map<String, Object> varMap = new HashMap<String, Object>();
			if (countersignInfo != null) {
				countersignInfo.appendDecidition(user, opinion
						.getOpinionString());
				varMap
						.put(
								EnumProcessInstanceFixedVariableNameSet.COUNTERSIGN_TASK_INFO_PREFIX
										.toString()
										+ ProcessSystemDeclareKeys.UNDERLINE
										+ taskInstance.getActivityName(),
								countersignInfo);
			}
			if (variableMap != null)
				varMap.putAll(variableMap);
			varMap
					.put(
							EnumProcessInstanceFixedVariableNameSet.PROCESS_INSTANCE_HELPER
									.toString(), helper);
			TaskInstanceVO taskVO = this.convertToVO(taskInstance);
			this.processEngine.getTaskService().completeTask(taskInstanceId,
					varMap);
			this.systemProcessLogService.saveOperateLog(taskVO
					.getProcessInstanceId(), helper.getProcessDefinitionName(),
					taskInstance, user, opinion, null);
		}
	}

	private Set<TaskInstanceVO> convertToTaskInstanceVO(List<Task> tasks) {
		Set<TaskInstanceVO> voSet = new HashSet<TaskInstanceVO>();
		for (Task task : tasks)
			voSet.add(this.convertToVO(task));
		return voSet;
	}

	public Set<Task> getListAllUnAssignedTaskInstanceByUser(User user,
			PageinationEntity page) {
		Set<String> idSet = this.getUserIdSet(user);
		List<Task> tasks = taskInstanceQueryDAO
				.getListByNamedQueryAndNamedParam(
						EnumSystemQueryNameSet.PROCESS_SYSTEM_QUERY_NAME_TASKINSTANCE_GETLISTBYIDSET,
						EnumTaskInstanceQueryParamNameSet.QUERY_PARAMETER_NAME_CANDIDATEIDS
								.getValue(), idSet);
		Set<Task> taskSet = new HashSet<Task>(tasks);
		return taskSet;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#getListTaskInstanceByUser(com.wilmar.process.entity.User)
	 */
	public List<Task> getListTakenTaskInstanceByUser(User user,
			PageinationEntity page) {
		List<Task> tasks = this.processEngine.getTaskService()
				.createTaskQuery().assignee(user.getId()).notSuspended()
				.orderDesc(TaskQuery.PROPERTY_CREATEDATE).list();
		return tasks;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#getListUnTakenTaskInstanceByOrganization(com.wilmar.process.entity.Organization)
	 */
	public Set<TaskInstanceVO> getListUnAssignedTaskInstanceByOrganization(
			Set<Organization> organizationSet, PageinationEntity page) {
		List<Task> tasks = taskInstanceQueryDAO
				.getListByNamedQueryAndNamedParam(
						EnumSystemQueryNameSet.PROCESS_SYSTEM_QUERY_NAME_TASKINSTANCE_GETLISTBYIDSET,
						EnumTaskInstanceQueryParamNameSet.QUERY_PARAMETER_NAME_CANDIDATEIDS
								.getValue(), organizationSet);
		return this.convertToTaskInstanceVO(tasks);
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#getListUnTakenTaskInstanceByRole(com.wilmar.process.entity.Role)
	 */
	public Set<TaskInstanceVO> getListUnAssignedTaskInstanceByRole(
			Set<Role> roleSet, PageinationEntity page) {
		List<Task> tasks = taskInstanceQueryDAO
				.getListByNamedQueryAndNamedParam(
						EnumSystemQueryNameSet.PROCESS_SYSTEM_QUERY_NAME_TASKINSTANCE_GETLISTBYIDSET,
						EnumTaskInstanceQueryParamNameSet.QUERY_PARAMETER_NAME_CANDIDATEIDS
								.getValue(), roleSet);
		return this.convertToTaskInstanceVO(tasks);
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#getListUnTakenTaskInstanceByUser(com.wilmar.process.entity.User)
	 */
	public Set<TaskInstanceVO> getListUnAssignedTaskInstanceByUser(
			Set<User> userSet, PageinationEntity page) {
		List<Task> tasks = taskInstanceQueryDAO
				.getListByNamedQueryAndNamedParam(
						EnumSystemQueryNameSet.PROCESS_SYSTEM_QUERY_NAME_TASKINSTANCE_GETLISTBYIDSET,
						EnumTaskInstanceQueryParamNameSet.QUERY_PARAMETER_NAME_CANDIDATEIDS
								.getValue(), userSet);
		return this.convertToTaskInstanceVO(tasks);
	}

	public IOrganizationService getOrganizationService() {
		return organizationService;
	}

	public IRoleService getRoleService() {
		return roleService;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#getTaskForm(java.lang.String)
	 */
	public String getTaskForm(String taskInstanceId)
			throws ObjectNotFoundException {
		Task taskInstance = this.processEngine.getTaskService().getTask(
				taskInstanceId);
		if (taskInstance == null) {
			throw new ObjectNotFoundException(
					"Here is no task instance or the task instance has been past due,the id is:"
							+ taskInstanceId);
		}
		return taskInstance.getFormResourceName();
	}

	public ITaskInstanceQueryDAO getTaskInstanceQueryDAO() {
		return taskInstanceQueryDAO;
	}

	public void setOrganizationService(IOrganizationService organizationService) {
		this.organizationService = organizationService;
	}

	public void setRoleService(IRoleService roleService) {
		this.roleService = roleService;
	}

	public void setTaskInstanceQueryDAO(
			ITaskInstanceQueryDAO taskInstanceQueryDAO) {
		this.taskInstanceQueryDAO = taskInstanceQueryDAO;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#takeTask(java.lang.String,
	 *      com.wilmar.process.entity.User)
	 */
	public synchronized void takeTask(String taskInstanceId, User user)
			throws PermissionDeniedException, TaskRepeatAcceptedException,
			TaskAlreadyTakenByAnotherUserException,
			TaskAlreadyProcessedException, ObjectNotFoundException {
		List<Participation> participations = this.processEngine
				.getTaskService().getTaskParticipations(taskInstanceId);
		Set<String> limits = this.getUserIdSet(user);
		boolean flag = false;
		for (Participation participation : participations) {
			if (limits.contains(participation.getUserId())) {
				flag = true;
				break;
			}
		}
		Task taskInstance = this.processEngine.getTaskService().getTask(
				taskInstanceId);
		if (taskInstance == null) {
			throw new TaskAlreadyProcessedException(
					"This task instance already been processed by another user!");
		}
		if (taskInstance.getAssignee() != null
				&& taskInstance.getAssignee().equalsIgnoreCase(user.getId())) {
			throw new TaskRepeatAcceptedException("User " + user.getId()
					+ " already toke this task instance! Do not take it again!");
		} else if (taskInstance.getAssignee() != null
				&& !taskInstance.getAssignee().equalsIgnoreCase(user.getId())) {
			throw new TaskAlreadyTakenByAnotherUserException(
					"This task instance already been taken by user "
							+ taskInstance.getAssignee());
		}
		if (flag && taskInstance != null) {
			ProcessInstanceHelper helper = this.systemProcessInstanceService
					.getProcessInstanceHelperById(taskInstance.getExecutionId());
			helper.addAssignInfo(taskInstance.getName(), user);
			this.processEngine
					.getExecutionService()
					.setVariable(
							taskInstance.getExecutionId(),
							EnumProcessInstanceFixedVariableNameSet.PROCESS_INSTANCE_HELPER
									.toString(), helper);
			this.processEngine.getTaskService().takeTask(taskInstanceId,
					user.getId());
			ProcessLog aLog = new ProcessLog();
			aLog.setEnterTime(new Date());
			aLog.setLogLevel(EnumProcessLogLevel.LOG_LEVEL_TWO);
			aLog.setOpinionType(EnumProcessOperateOpinionType.MESSAGE);
			aLog.setNodeDesc(taskInstance.getDescription());
			aLog.setNodeName(taskInstance.getName());
			aLog.setOperator(user.getId());
			aLog.setOperatorName(user.getName());
			aLog.setOuterSystem(user.getOuterSystem());
			aLog.setExecutionId(taskInstanceId);
			TaskInstanceVO taskVO = this.convertToVO(taskInstance);
			aLog.setProcessInstanceId(taskVO.getProcessInstanceId());
			aLog.setProcessDefinitionName(taskVO.getProcessDefinitionName());
			aLog.setOutCome("Take Task Instance");
			aLog.setLeaveTime(new Date());
			this.systemProcessLogService.saveProcessLog(aLog);
		} else {
			throw new PermissionDeniedException(
					"This task is not assigned to you! You can't take it!");
		}
	}

	private Set<String> getUserIdSet(User user) {
		Set<String> result = new HashSet<String>();
		result.add(user.getId());
		Set<Role> userRoleSet = this.roleService.getListRolesByUser(user);
		Set<Organization> userOrganizationSet = this.organizationService
				.getListAllOrganizationsByUser(user);
		if (userRoleSet != null) {
			for (Role role : userRoleSet) {
				result.add(role.getId());
			}
		}
		if (userOrganizationSet != null) {
			for (Organization org : userOrganizationSet) {
				result.add(org.getId());
			}
		}
		return result;

	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#popTask(java.lang.String,
	 *      com.wilmar.process.entity.User)
	 */
	public synchronized void popTask(String taskInstanceId, User user)
			throws PermissionDeniedException {
		Task taskInstance = this.processEngine.getTaskService().getTask(
				taskInstanceId);
		if (taskInstance != null
				&& user.getId().equals(taskInstance.getAssignee())) {
			this.processEngine.getTaskService().assignTask(taskInstanceId, "");
			ProcessLog aLog = new ProcessLog();
			aLog.setEnterTime(new Date());
			aLog.setLogLevel(EnumProcessLogLevel.LOG_LEVEL_TWO);
			aLog.setOpinionType(EnumProcessOperateOpinionType.MESSAGE);
			aLog.setNodeDesc(taskInstance.getDescription());
			aLog.setNodeName(taskInstance.getName());
			aLog.setOperator(user.getId());
			aLog.setOperatorName(user.getName());
			aLog.setOuterSystem(user.getOuterSystem());
			aLog.setExecutionId(taskInstanceId);
			TaskInstanceVO taskVO = this.convertToVO(taskInstance);
			aLog.setProcessInstanceId(taskVO.getProcessInstanceId());
			aLog.setProcessDefinitionName(taskVO.getProcessDefinitionName());
			aLog.setOutCome("Pop Task Instance");
			aLog.setLeaveTime(new Date());
			this.systemProcessLogService.saveProcessLog(aLog);
		} else {
			throw new PermissionDeniedException(
					"This task is not assigned to you! You can't pop it!");
		}

	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#getDataByTaskInstanceId(java.lang.String)
	 */
	public Map<String, Object> getDataByTaskInstanceId(String taskInstanceId) {
		Set<String> variable_nameSet = this.processEngine.getTaskService()
				.getVariableNames(taskInstanceId);
		Map<String, Object> variableMap = this.processEngine.getTaskService()
				.getVariables(taskInstanceId, variable_nameSet);
		return variableMap;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#getOutComes(java.lang.String)
	 */
	public Set<String> getOutComes(String taskInstanceId)
			throws ObjectNotFoundException {
		Set<String> result = this.processEngine.getTaskService().getOutcomes(
				taskInstanceId);
		Set<String> finalResult = new HashSet<String>();
		if (result == null)
			throw new ObjectNotFoundException(
					"Task instance not been found or there are no outcomes for this task instance!");
		for (String oneResult : result) {
			boolean found = false;
			for (String filtered : ProcessSystemDeclareKeys.PROCESS_SYSTEM_FILTERED_TASKINSTANCE_OUTCOME) {
				if (filtered.equals(oneResult)) {
					found = true;
				}
			}
			if (!found) {
				finalResult.add(oneResult);
			}
		}
		return finalResult;
	}

	/**
	 * @return the systemProcessLogService
	 */
	public ISystemProcessLogService getSystemProcessLogService() {
		return systemProcessLogService;
	}

	/**
	 * @param systemProcessLogService
	 *            the systemProcessLogService to set
	 */
	public void setSystemProcessLogService(
			ISystemProcessLogService systemProcessLogService) {
		this.systemProcessLogService = systemProcessLogService;
	}

	/**
	 * @see com.wilmar.process.core.services.api.IBaseService#convertToVO(java.lang.Object)
	 */
	public TaskInstanceVO convertToVO(Task entity) {
		Execution ex = this.processEngine.getExecutionService()
				.findExecutionById(entity.getExecutionId());
		ProcessInstance pi = null;
		ProcessDefinition pd = null;
		if (ex != null) {
			while (!ex.getIsProcessInstance()) {
				ex = ex.getProcessInstance();
			}
			pi = (ProcessInstance) ex;
			pd = this.processEngine.getRepositoryService()
					.createProcessDefinitionQuery().processDefinitionId(
							pi.getProcessDefinitionId()).uniqueResult();
		}
		TaskInstanceVO vo = new TaskInstanceVO(entity, pi, pd);
		return vo;
	}

	/**
	 * @see com.wilmar.process.core.services.api.IBaseService#convertToVOList(java.util.List)
	 */
	public List<TaskInstanceVO> convertToVOList(Collection<Task> entityList) {
		List<TaskInstanceVO> voList = new ArrayList<TaskInstanceVO>(entityList
				.size());
		for (Task task : entityList) {
			voList.add(this.convertToVO(task));
		}
		return voList;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#getTakenTaskInstanceCountByUser(com.wilmar.process.entity.User)
	 */
	public Long getTakenTaskInstanceCountByUser(User user) {
		return this.taskInstanceQueryDAO
				.getTakenTaskCountByUserId(user.getId());
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#getUnAssignedTaskInstanceCountByUser(com.wilmar.process.entity.User)
	 */
	public Long getUnAssignedTaskInstanceCountByUser(User user) {
		Set<String> userIdSet = this.getUserIdSet(user);
		return this.taskInstanceQueryDAO
				.getUnAssignedTaskCountByIdSet(userIdSet);
	}

	public List<Task> getCurrentActiveTaskInstanceList(String processInstanceId) {
		return this.processEngine.getTaskService().createTaskQuery()
				.processInstanceId(processInstanceId).notSuspended().list();
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#getListAllUnAssignedTaskInstanceByUser(com.wilmar.process.entity.User,
	 *      com.wilmar.process.entity.query.ProcessUnassignTaskQueryObject)
	 */
	public Set<Task> getListAllUnAssignedTaskInstanceByUser(User user,
			ProcessUnassignTaskQueryObject queryObject) {
		Set<String> userIds = this.getUserIdSet(user);
		List<Task> tasks = this.taskInstanceQueryDAO
				.getUnassignTaskListByQueryObject(queryObject, userIds);
		Set<Task> taskSet = new HashSet<Task>(tasks);
		return taskSet;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#getListTakenTaskInstanceByUser(com.wilmar.process.entity.User,
	 *      com.wilmar.common.util.PageinationEntity,
	 *      com.wilmar.process.entity.query.ProcessTakenTaskQueryObject)
	 */
	public List<Task> getListTakenTaskInstanceByUser(User user,
			ProcessTakenTaskQueryObject queryObject) {
		String userId = user.getId();
		List<Task> tasks = this.taskInstanceQueryDAO
				.getTakenTaskListByQueryObject(queryObject, userId);
		return tasks;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#addComment(java.lang.String,
	 *      java.lang.String, com.wilmar.process.entity.User, boolean)
	 */
	public void addComment(String taskInstanceId, String comment, User user,
			boolean forceComment) throws PermissionDeniedException {
		Task taskInstance = this.processEngine.getTaskService().getTask(
				taskInstanceId);
		if ((taskInstance.getAssignee() != null && forceComment)
				|| (!forceComment && !user.getId().equalsIgnoreCase(
						taskInstance.getAssignee()))) {
			throw new PermissionDeniedException(
					"This task is not assigned to you! You can't add comment!");
		} else {
			// this.processEngine.getTaskService().addTaskComment(taskInstanceId,
			// comment);
			ProcessLog aLog = new ProcessLog();
			aLog.setOpinionString(comment);
			aLog.setEnterTime(new Date());
			aLog.setLogLevel(EnumProcessLogLevel.LOG_LEVEL_THREE);
			aLog.setOpinionType(EnumProcessOperateOpinionType.MESSAGE);
			aLog.setNodeDesc(taskInstance.getDescription());
			aLog.setNodeName(taskInstance.getName());
			aLog.setOperator(user.getId());
			aLog.setOperatorName(user.getName());
			aLog.setOuterSystem(user.getOuterSystem());
			aLog.setExecutionId(taskInstanceId);
			TaskInstanceVO taskVO = this.convertToVO(taskInstance);
			aLog.setProcessInstanceId(taskVO.getProcessInstanceId());
			aLog.setProcessDefinitionName(taskVO.getProcessDefinitionName());
			aLog.setOutCome("Add Task Instance Comment");
			aLog.setLeaveTime(new Date());
			this.systemProcessLogService.saveProcessLog(aLog);
		}
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#addCommentReply(java.lang.String,
	 *      java.lang.String, com.wilmar.process.entity.User)
	 */
	public void addCommentReply(String taskInstanceId, String commentId,
			String reply, User user) {
		Task taskInstance = this.processEngine.getTaskService().getTask(
				taskInstanceId);
		// this.processEngine.getTaskService().addReplyComment(commentId,
		// reply);
		ProcessLog aLog = new ProcessLog();
		aLog.setOpinionString(reply);
		aLog.setEnterTime(new Date());
		aLog.setLogLevel(EnumProcessLogLevel.LOG_LEVEL_THREE);
		aLog.setOpinionType(EnumProcessOperateOpinionType.MESSAGE);
		aLog.setNodeDesc(taskInstance.getDescription());
		aLog.setNodeName(taskInstance.getName());
		aLog.setOperator(user.getId());
		aLog.setOperatorName(user.getName());
		aLog.setOuterSystem(user.getOuterSystem());
		aLog.setExecutionId(taskInstanceId);
		TaskInstanceVO taskVO = this.convertToVO(taskInstance);
		aLog.setProcessInstanceId(taskVO.getProcessInstanceId());
		aLog.setProcessDefinitionName(taskVO.getProcessDefinitionName());
		aLog.setOutCome("Add Task Instance Comment Reply");
		aLog.setLeaveTime(new Date());
		this.systemProcessLogService.saveProcessLog(aLog);
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#getDetailById(java.lang.String)
	 */
	public Task getDetailById(String taskInstanceId)
			throws ObjectNotFoundException {
		Task ti = this.processEngine.getTaskService().getTask(taskInstanceId);
		if (ti == null)
			throw new ObjectNotFoundException(
					"There is no task instance's id is:" + taskInstanceId);
		return ti;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#createOrUpdateVariable(java.lang.String,
	 *      java.lang.String, java.lang.Object)
	 */
	public void createOrUpdateVariable(String taskInstanceId, String name,
			Object value) {
		try {
			EnumProcessInstanceFixedVariableNameSet.valueOf(name);
		} catch (Exception e) {
			Map<String, Object> variables = new HashMap<String, Object>();
			variables.put(name, value);
			this.createOrUpdateVariables(taskInstanceId, variables);
		}
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#getVariable(java.lang.String,
	 *      java.lang.String)
	 */
	public Object getVariable(String taskInstanceId, String variableName)
			throws ObjectNotFoundException {
		Object value = this.processEngine.getTaskService().getVariable(
				taskInstanceId, variableName);
		if (value == null)
			throw new ObjectNotFoundException("Here is no variable named:"
					+ variableName + " in task instance:" + taskInstanceId);
		return value;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#createOrUpdateVariables(java.lang.String,
	 *      java.util.Map)
	 */
	@SuppressWarnings("unchecked")
	public void createOrUpdateVariables(String taskInstanceId,
			Map<String, ?> variableMap) {
		Iterator<String> iter = variableMap.keySet().iterator();
		while (iter.hasNext()) {
			String vname = iter.next();
			try {
				EnumProcessInstanceFixedVariableNameSet.valueOf(vname);
				variableMap.remove(vname);
			} catch (Exception e) {
			}
		}
		this.processEngine.getTaskService().setVariables(taskInstanceId,
				(Map<String, Object>) variableMap);
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#getTaskDescription(java.lang.String)
	 */
	public String getTaskDescription(String taskInstanceId)
			throws ObjectNotFoundException {
		Task taskInstance = this.processEngine.getTaskService().getTask(
				taskInstanceId);
		if (taskInstance == null) {
			throw new ObjectNotFoundException(
					"Here is no task instance , the id is:" + taskInstanceId);
		}
		return taskInstance.getDescription();
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemTaskInstanceService#createSubTaskInstance(java.lang.String,
	 *      com.wilmar.process.entity.TaskInstanceProperties)
	 */
	public Task createSubTaskInstance(String parentTakeInstanceId,
			TaskInstanceProperties properties) {
		Task subTask = this.processEngine.getTaskService().newTask(
				parentTakeInstanceId);
		subTask.setDescription(properties.getTaskDescription());
		subTask.setName(properties.getTaskName());
		subTask.setPriority(properties.getTaskPriority());
		return null;
	}

	/**
	 * @return the processEngine
	 */
	public ProcessEngine getProcessEngine() {
		return processEngine;
	}

	/**
	 * @param processEngine
	 *            the processEngine to set
	 */
	public void setProcessEngine(ProcessEngine processEngine) {
		this.processEngine = processEngine;
	}

	/**
	 * @return the systemProcessInstanceService
	 */
	public ISystemProcessInstanceService getSystemProcessInstanceService() {
		return systemProcessInstanceService;
	}

	/**
	 * @param systemProcessInstanceService
	 *            the systemProcessInstanceService to set
	 */
	public void setSystemProcessInstanceService(
			ISystemProcessInstanceService systemProcessInstanceService) {
		this.systemProcessInstanceService = systemProcessInstanceService;
	}
}
